﻿#region copyright
// Halcyone - Silverlight Application Framework
// Copyright (C) 2009 - 2010 Alexey Zakharov (B&Z LLC)
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;

namespace Witcraft.Halcyone.ASPFacility
{
    ///<summary>
    ///</summary>
    public class RestControllerRoutesExtracter
    {
        private const string Controller = "Controller";

        ///<summary>
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<returns></returns>
        public static RouteCollection Extract<T>()
        {
            var routeCollection = new RouteCollection();
            Assembly assembly = typeof (T).Assembly;
            IEnumerable<Type> controllers = assembly.GetTypes().Where(IsRestControllerType);
            foreach (Type controller in controllers)
            {
                string serviceName = controller.Name.Substring(0, controller.Name.Length - Controller.Length);

                MethodInfo[] actions = controller.GetMethods(BindingFlags.Public | BindingFlags.Instance);

                foreach (MethodInfo methodInfo in actions)
                {
                    string path = serviceName + "/" + methodInfo.Name;
                    var route = new Route(path, new MvcRouteHandler())
                                    {
                                        Defaults = new RouteValueDictionary(),
                                        DataTokens = new RouteValueDictionary()
                                    };
                    route.Defaults["controller"] = serviceName;
                    route.Defaults["action"] = methodInfo.Name;
                    route.DataTokens["Namespaces"] = new[] {controller.Namespace};
                    routeCollection.Add(Guid.NewGuid().ToString(), route);
                }
            }
            return routeCollection;
        }

        ///<summary>
        ///</summary>
        ///<param name="type"></param>
        ///<returns></returns>
        public static bool IsRestControllerType(Type type)
        {
            return type.IsClass
                   && !type.IsAbstract
                   && type.IsDefined(typeof (RestServiceAttribute), true)
                   && type.IsSubclassOf(typeof (Controller))
                   && type.Name.EndsWith(Controller, StringComparison.InvariantCultureIgnoreCase);
        }
    }
}